package server.core;

import server.*;
import server.util.LifecycleSupport;

import javax.servlet.ServletException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/*
标准的管道实现类,调用管道的invoke方法后，管道会创建一个StandardPipelineValveContext对象并调用其invokeNext方法,
StandardPipelineValveContext的invokeNext方法会调用第一个阀的invoke方法并将自身传入该方法,第一个阀可以根据情况
选择是否调用第二个阀执行(前面的阀可以控制后面的阀是否执行)。
 */
/*
2023/3/1 该类内容全部写完,后续直接使用,无需修改
by cyl
 */
public class StandardPipeline implements Pipeline, Contained, Lifecycle {
    //管道所在的容器
    protected Container container = null;
    //基本阀
    protected Valve basic = null;
    //调试等级
    protected int debug = 0;
    //组件信息
    protected String info = "server.core.StandardPipeline/1.0";
    //生命周期接口支持
    protected LifecycleSupport lifecycle = new LifecycleSupport(this);
    //组件是否启动
    protected boolean started = false;
    //管道的非基本阀
    protected List<Valve> valves = new ArrayList<>();

    public StandardPipeline(Container container) {
        setContainer(container);
    }
    //方法-------------------------------------------------------------------------
    protected void log(String message) {
        Logger logger = null;
        if (container != null)
            logger = container.getLogger();
        if (logger != null)
            logger.log("StandardPipeline[" + container.getName() + "]: " + message);
        else
            System.out.println("StandardPipeline[" + container.getName() + "]: " + message);
    }
    protected void log(String message, Throwable throwable) {
        Logger logger = null;
        if (container != null)
            logger = container.getLogger();
        if (logger != null)
            logger.log("StandardPipeline[" + container.getName() + "]: " + message, throwable);
        else {
            System.out.println("StandardPipeline[" + container.getName() + "]: " + message);
            throwable.printStackTrace(System.out);
        }
    }
    //getter-------------------------------------------------------------------------

    public String getInfo() {
        return info;
    }

    //setter-------------------------------------------------------------------------


    //实现Pipeline接口-------------------------------------------------------------------------

    @Override
    public Valve getBasic() {
        return basic;
    }

    @Override
    public void setBasic(Valve valve) {
        if (basic == valve)
            return;
        if (basic != null) {
            if (started && basic instanceof Lifecycle) {
                try {
                    ((Lifecycle) basic).stop();
                } catch (LifecycleException e) {
                    log("StandardPipeline.setBasic: stop", e);
                }
            }
            if (basic instanceof Contained) {
                try {
                    ((Contained) basic).setContainer(null);
                } catch (Throwable t) {

                }
            }
        }
        if (valve == null)
            return;
        if (valve instanceof Contained)
            ((Contained) valve).setContainer(container);
        if (started && valve instanceof Lifecycle) {
            try {
                ((Lifecycle) valve).stop();
            } catch (LifecycleException e) {
                log("StandardPipeline.setBasic: start", e);
                return;
            }
        }
        basic = valve;
    }

    @Override
    public void addValve(Valve valve) {
        if (valve instanceof Contained) {
            ((Contained) valve).setContainer(container);
        }
        if (started && valve instanceof Lifecycle) {
            try {
                ((Lifecycle) valve).start();
            } catch (LifecycleException e) {
                log("StandardPipeline.addValve: start: ", e);
            }
        }
        synchronized (valves) {
            valves.add(valve);
        }
    }

    @Override
    public List<Valve> getValves() {
        if (basic == null)
            return valves;
        List<Valve> newValves = null;
        synchronized (valves) {
            newValves = new ArrayList<>(valves);
        }
        newValves.add(basic);
        return newValves;
    }

    @Override
    public void removeValve(Valve valve) {
        synchronized (valves) {
            valves.remove(valve);
        }
        if (valve instanceof Contained) {
            try {
                ((Contained) valve).setContainer(null);
            } catch (Throwable t) {

            }

        }
        if (started && valve instanceof Lifecycle) {
            try {
                ((Lifecycle) valve).stop();
            } catch (LifecycleException e) {
                log("StandardPipeline.removeValve: stop: ", e);
            }
        }
    }

    @Override
    public void invoke(Request request, Response response) throws IOException, ServletException {
        new StandardPipelineValveContext().invokeNext(request, response);
    }

    //实现Lifecycle接口-------------------------------------------------------------------------

    @Override
    public void addLifecycleListener(LifecycleListener listener) {
        lifecycle.addLifecycleListener(listener);
    }

    @Override
    public LifecycleListener[] findLifecycleListeners() {
        return lifecycle.findLifecycleListeners();
    }

    @Override
    public void removeLifecycleListener(LifecycleListener listener) {
        lifecycle.removeLifecycleListener(listener);
    }

    @Override
    public synchronized void start() throws LifecycleException {
        if (started)
            throw new LifecycleException("Pipeline has already been started");
        lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
        started = true;
        for (Valve valve : valves) {
            if (valve instanceof Lifecycle)
                ((Lifecycle) valve).start();
        }
        if (basic != null && basic instanceof Lifecycle)
            ((Lifecycle) basic).start();
        lifecycle.fireLifecycleEvent(START_EVENT, null);
        lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
    }

    @Override
    public synchronized void stop() throws LifecycleException {
        if (!started)
            throw new LifecycleException("Pipeline has not been started");
        lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
        lifecycle.fireLifecycleEvent(STOP_EVENT, null);
        started = false;
        if (basic != null && basic instanceof Lifecycle)
            ((Lifecycle) basic).stop();
        for (Valve valve : valves) {
            if (valve instanceof Lifecycle)
                ((Lifecycle) valve).stop();
        }
        lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
    }

    //实现Contained接口-------------------------------------------------------------------------
    public void setContainer(Container container) {
        this.container = container;
    }

    @Override
    public Container getContainer() {
        return container;
    }
    //内部类StandardPipelineValveContext-----------------------------------------------------------
    /*
    用于控制管道中所有阀执行循序的类,每个阀都可以选择是否执行下一个阀(是否调用invokeNext方法)
     */
    protected class StandardPipelineValveContext implements ValveContext {
        //下一个要执行的阀的下标
        protected int index = 0;
        @Override
        public String getInfo() {
            return info;
        }

        @Override
        public void invokeNext(Request request, Response response) throws IOException, ServletException {
            int i = index++;
            //还有非基础阀未执行
            if (i < valves.size()) {
                Valve valve = valves.get(i);
                valve.invoke(request, response, this);
            } else if (i == valves.size()){
                //其他阀执行完,执行基础阀
                basic.invoke(request, response, this);
            } else {
                throw new ServletException("No more Valves in the Pipeline processing this request");
            }
        }
    }

}
